package cas.ihep.spark.util;

import java.io.PrintStream;
import java.util.Formatter;
import java.util.concurrent.atomic.AtomicInteger;

public class LogEnv {

    public enum LogLevel{
        Debug,
        Info,
        Warn,
        Error,
        Fatal,
    }
    private static final LogEnv environ=new LogEnv();

    private AtomicInteger logLevel;
    private PrintStream out;

    public void setLogLevel(LogLevel l){
        logLevel.set(l.ordinal());
    }

    public void setLogLevel(String lg){
        int l;
        if ("info".equalsIgnoreCase(lg)) {
            l=INFO;
            lg="info";
        }else if("debug".equalsIgnoreCase(lg)){
            l=DEBUG;
            lg="debug";
        }else if("warn".equalsIgnoreCase(lg) || "warning".equalsIgnoreCase(lg)){
            l=WARN;
            lg="warn";
        }else if("error".equalsIgnoreCase(lg)){
            l=ERROR;
            lg="error";
        }else if("fatal".equalsIgnoreCase(lg)){
            l=FATAL;
            lg="fatal";
        }else{
            l=INFO;
            print(WARN,"Unrecognized log level `%s'",lg);
            lg="info";
        }
        print(INFO,"Set log level to `%s'",lg);
        logLevel.set(l);
    }
    public synchronized void setLogger(PrintStream os){
        out=os;
    }

    public static LogEnv getInstance(){
        return environ;
    }

    private LogEnv(){
        out=System.err;
        logLevel=new AtomicInteger(1);
    }

    private static final int DEBUG=0;
    private static final int INFO=1;
    private static final int WARN=2;
    private static final int ERROR=3;
    private static final int FATAL=4;

    private void print(int level,String format,Object ...varargs){
        String prefix;
        switch (level){
            case DEBUG:
                prefix="[DEBUG] ";
                break;
            case INFO:
                prefix="[INFO] ";
                break;
            case WARN:
                prefix="[WARN] ";
                break;
            case ERROR:
                prefix="[ERROR] ";
                break;
            case FATAL:
                prefix="[FATAL] ";
                break;
            default:
                throw new IllegalArgumentException("Illegal log level");
        }
        if(varargs.length==0){
            out.print(prefix);
            out.println(format);
        }else{
            StringBuilder builder=new StringBuilder(format.length()+24);
            builder.append(prefix);
            new Formatter(builder).format(format,varargs);
            out.println(builder);
        }
    }

    public void debug(String format,Object ... varargs){
        if(logLevel.get()<=DEBUG){
            print(DEBUG,format,varargs);
        }
    }

    public void info(String format,Object ... varargs){
        if(logLevel.get()<=INFO){
            print(INFO,format,varargs);
        }
    }

    public void warn(String format,Object ... varargs){
        if(logLevel.get()<=WARN){
            print(WARN,format,varargs);
        }
    }

    public void error(String format,Object ... args){
        if(logLevel.get()<=ERROR){
            print(ERROR,format,args);
        }
    }

    public void fatal(String format,Object ... args){
        if(logLevel.get()<=FATAL){
            print(FATAL,format,args);
        }
    }
}
